home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / enigma / earcd / emula / arosdv19.lha / AROS / dos / matchpattern.c < prev    next >
C/C++ Source or Header  |  1996-10-24  |  9KB  |  311 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: matchpattern.c,v 1.2 1996/10/24 15:50:32 aros Exp $
  4.     $Log: matchpattern.c,v $
  5.     Revision 1.2  1996/10/24 15:50:32  aros
  6.     Use the official AROS macros over the __AROS versions.
  7.  
  8.     Revision 1.1  1996/09/11 12:54:46  digulla
  9.     A couple of new DOS functions from M. Fleischer
  10.  
  11.     Desc:
  12.     Lang: english
  13. */
  14. #include <exec/memory.h>
  15. #include <clib/exec_protos.h>
  16. #include <dos/dosextens.h>
  17. #include "dos_intern.h"
  18.  
  19. /*****************************************************************************
  20.  
  21.     NAME */
  22.     #include <clib/dos_protos.h>
  23.  
  24.     AROS_LH2(BOOL, MatchPattern,
  25.  
  26. /*  SYNOPSIS */
  27.     AROS_LHA(STRPTR, pat, D1),
  28.     AROS_LHA(STRPTR, str, D2),
  29.  
  30. /*  LOCATION */
  31.     struct DosLibrary *, DOSBase, 141, Dos)
  32.  
  33. /*  FUNCTION
  34.  
  35.     INPUTS
  36.  
  37.     RESULT
  38.  
  39.     NOTES
  40.  
  41.     EXAMPLE
  42.  
  43.     BUGS
  44.  
  45.     SEE ALSO
  46.  
  47.     INTERNALS
  48.  
  49.     HISTORY
  50.     29-10-95    digulla automatically created from
  51.                 dos_lib.fd and clib/dos_protos.h
  52.  
  53. *****************************************************************************/
  54. {
  55.     AROS_LIBFUNC_INIT
  56.     AROS_LIBBASE_EXT_DECL(struct DosLibrary *,DOSBase)
  57.  
  58.     /*
  59.         A simple method for pattern matching with multiple wildcards:
  60.         I use markers that consist of both a pointer into the string
  61.         and one into the pattern. The marker simply follows the string
  62.         and everytime it hits a wildcard it's split into two new markers
  63.         (one to assume that the wildcard match has ended and one to assume
  64.          that it continues). If a marker doesn't fit any longer it's
  65.         removed and if all of them are gone the pattern mismatches.
  66.         OTOH if any of the markers reaches the end of both the string
  67.         and the pattern simultaneously the pattern matches the string.
  68.     */
  69.     STRPTR s;
  70.     LONG match=0;
  71.     struct markerarray ma, *macur=&ma, *cur2;
  72.     LONG macnt=0, cnt2;
  73.     ULONG level;
  74.     UBYTE a, b, c, t;
  75.     LONG error;
  76. #define ERROR(a) { error=(a); goto end; }
  77.  
  78.     ma.next=ma.prev=NULL;
  79.     for(;;)
  80.         switch(*pat)
  81.         {
  82.             case MP_MULT: /* _#(_a) */
  83.                 /* Split the marker */
  84.                 PUSH(0,++pat,str);
  85.                 level=1;
  86.                 for(;;)
  87.                 {
  88.                     c=*pat++;
  89.                     if(c==MP_MULT)
  90.                         level++;
  91.                     else if(c==MP_MULT_END)
  92.                         if(!--level)
  93.                             break;
  94.                 }
  95.                 break;
  96.             case MP_MULT_END: /* #(a_)_ */
  97.                 /* Go back to the start of the block */
  98.                 level=1;
  99.                 for(;;)
  100.                 {
  101.                     c=*--pat;
  102.                     if(c==MP_MULT_END)
  103.                         level++;
  104.                     else if(c==MP_MULT)
  105.                         if(!--level)
  106.                             break;
  107.                 }
  108.                 break;
  109.             case MP_NOT: /* _~(_a) */
  110.                 s=++pat;
  111.                 level=1;
  112.                 for(;;)
  113.                 {
  114.                     c=*s++;
  115.                     if(c==MP_NOT)
  116.                         level++;
  117.                     else if(c==MP_NOT_END)
  118.                         if(!--level)
  119.                             break;
  120.                 }
  121.                 PUSH(1,s,str);
  122.                 break;
  123.             case MP_NOT_END: /* ~(a_)_ */
  124.                 cnt2=macnt;
  125.                 cur2=macur;
  126.                 do
  127.                 {
  128.                     cnt2--;
  129.                     if(cnt2<0)
  130.                     {
  131.                         cnt2=127;
  132.                         cur2=cur2->prev;
  133.                     }
  134.                 }while(!cur2->marker[cnt2].type);
  135.                 if(!*str++)
  136.                 {
  137.                     macnt=cnt2;
  138.                     macur=cur2;
  139.                 }else
  140.                     if(str>cur2->marker[cnt2].str)
  141.                         cur2->marker[cnt2].str=str;
  142.                 POP(t,pat,str);
  143.                 if(t&&*str)
  144.                 { PUSH(1,pat,str+1); }
  145.                 break;
  146.             case MP_OR: /* ( */
  147.                 s=++pat;
  148.                 level=1;
  149.                 for(;;)
  150.                 {
  151.                     c=*s++;
  152.                     if(c==MP_OR)
  153.                         level++;
  154.                     else if(c==MP_OR_NEXT)
  155.                     {
  156.                         if(level==1)
  157.                         { PUSH(0,s,str); }
  158.                     }else if(c==MP_OR_END)
  159.                         if(!--level)
  160.                             break;
  161.                 }
  162.                 break;
  163.             case MP_OR_NEXT: /* | */
  164.                 pat++;
  165.                 level=1;
  166.                 for(;;)
  167.                 {
  168.                     c=*pat++;
  169.                     if(c==MP_OR)
  170.                         level++;
  171.                     else if(c==MP_OR_END)
  172.                         if(!--level)
  173.                             break;
  174.                 }
  175.                 break;
  176.             case MP_OR_END: /* ) */
  177.                 pat++;
  178.                 break;
  179.             case MP_SINGLE: /* ? */
  180.                 pat++;
  181.                 if(*str)
  182.                     str++;
  183.                 else
  184.                 {
  185.                     POP(t,pat,str);
  186.                     if(t&&*str)
  187.                     { PUSH(1,pat,str+1); }
  188.                 }
  189.                 break;
  190.             case MP_SET: /* [ */
  191.                 pat++;
  192.                 for(;;)
  193.                 {
  194.                     a=b=*pat++;
  195.                     if(a==MP_SET_END)
  196.                     {
  197.                         POP(t,pat,str);
  198.                         if(t&&*str)
  199.                         { PUSH(1,pat,str+1); }
  200.                         break;
  201.                     }
  202.                     if(a==MP_ESCAPE)
  203.                         a=b=*pat++ +0x80;
  204.                     else if(a==MP_DASH)
  205.                     {
  206.                         a=*pat++;
  207.                         if(a==MP_ESCAPE)
  208.                             a=*pat++ +0x80;
  209.                         b=*pat++;
  210.                         if(b==MP_ESCAPE)
  211.                             b=*pat++ +0x80;
  212.                     }
  213.                     if(*str>=a&&*str<=b)
  214.                     {
  215.                         str++;
  216.                         while(*pat++!=MP_SET_END)
  217.                             ;
  218.                         break;
  219.                     }
  220.                 }
  221.                 break;
  222.             case MP_NOT_SET: /* [~ */
  223.                 if(!*str)
  224.                 {
  225.                     POP(t,pat,str);
  226.                     if(t&&*str)
  227.                     { PUSH(1,pat,str+1); }
  228.                     break;
  229.                 }
  230.                 pat++;
  231.                 for(;;)
  232.                 {
  233.                     a=b=*pat++;
  234.                     if(a==MP_SET_END)
  235.                     {
  236.                         str++;
  237.                         break;
  238.                     }
  239.                     if(a==MP_ESCAPE)
  240.                         a=b=*pat++ +0x80;
  241.                     else if(a==MP_DASH)
  242.                     {
  243.                         a=*pat++;
  244.                         if(a==MP_ESCAPE)
  245.                             a=*pat++ +0x80;
  246.                         b=*pat++;
  247.                         if(b==MP_ESCAPE)
  248.                             b=*pat++ +0x80;
  249.                     }
  250.                     if(*str>=a&&*str<=b)
  251.                     {
  252.                         POP(t,pat,str);
  253.                         if(t&&*str)
  254.                         { PUSH(1,pat,str+1); }
  255.                         break;
  256.                     }
  257.                 }
  258.                 break;
  259.             case MP_ALL: /* #? */
  260.                 /* This often used pattern has extra treatment to be faster */
  261.                 if(*str)
  262.                 { PUSH(0,pat,str+1); }
  263.                 pat++;
  264.                 break;
  265.             case 0:
  266.                 if(!*str)
  267.                 {
  268.                     match=1;
  269.                     ERROR(0);
  270.                 }else
  271.                 {
  272.                     POP(t,pat,str);
  273.                     if(t&&*str)
  274.                     { PUSH(1,pat,str+1); }
  275.                 }
  276.                 break;
  277.             case MP_ESCAPE:
  278.                 pat++;
  279.                 if(0x80+*pat++==*str)
  280.                     str++;
  281.                 else
  282.                 {
  283.                     POP(t,pat,str);
  284.                     if(t&&*str)
  285.                     { PUSH(1,pat,str+1); }
  286.                 }
  287.                 break;
  288.             default:
  289.                 if(*pat++==*str)
  290.                     str++;
  291.                 else
  292.                 {
  293.                     POP(t,pat,str);
  294.                     if(t&&*str)
  295.                     { PUSH(1,pat,str+1); }
  296.                 }
  297.                 break;
  298.         }
  299. end:
  300.     macur=ma.next;
  301.     while(macur!=NULL)
  302.     {
  303.         struct markerarray *next=macur->next;
  304.         FreeMem(macur,sizeof(struct markerarray));
  305.         macur=next;
  306.     }
  307.     ((struct Process *)FindTask(NULL))->pr_Result2=error;
  308.     return match;
  309.     AROS_LIBFUNC_EXIT
  310. } /* MatchPattern */
  311.